package com.spic.business.manual.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.data.RowRenderData;
import com.deepoove.poi.data.Rows;
import com.deepoove.poi.plugin.table.LoopColumnTableRenderPolicy;
import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy;
import com.spic.business.config.TemplateConfig;
import com.spic.business.manual.domain.*;
import com.spic.business.manual.mapper.SecurityCheckManualMapper;
import com.spic.business.manual.policy.SchedulePolicy;
import com.spic.business.manual.service.ISecurityCheckManualService;
import com.spic.common.core.utils.DateUtils;
import com.spic.common.core.utils.SecurityUtils;
import com.spic.common.core.utils.StringUtils;
import com.spic.common.core.web.domain.AjaxResult;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.TextStyle;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 迎检报告信息主Service业务层处理
 *
 * @author spic
 * @date 2022-06-13
 */
@Service
public class SecurityCheckManualServiceImpl implements ISecurityCheckManualService
{
    @Autowired
    private SecurityCheckManualMapper securityCheckManualMapper;

    private Logger logger = LoggerFactory.getLogger(SecurityCheckManualServiceImpl.class);
    @Autowired
    private TemplateConfig templateConfig;
    /**
     * 查询迎检报告信息主
     *
     * @param id 迎检报告信息主主键
     * @return 迎检报告信息主
     */
    @Override
    public SecurityCheckManual selectSecurityCheckManualById(Long id)
    {
        return securityCheckManualMapper.selectSecurityCheckManualById(id);
    }

    /**
     * 查询迎检报告信息主列表
     *
     * @param securityCheckManual 迎检报告信息主
     * @return 迎检报告信息主
     */
    @Override
    public List<SecurityCheckManual> selectSecurityCheckManualList(SecurityCheckManual securityCheckManual)
    {
        return securityCheckManualMapper.selectSecurityCheckManualList(securityCheckManual);
    }

    /**
     * 新增迎检报告信息主
     *
     * @param securityCheckManual 迎检报告信息主
     * @return 结果
     */
    @Transactional
    @Override
    public int insertSecurityCheckManual(SecurityCheckManual securityCheckManual)
    {
        Date now = DateUtils.getNowDate();
        securityCheckManual.setCreateBy(SecurityUtils.getUserId()+"");
        securityCheckManual.setCreateTime(now);
        int rows = securityCheckManualMapper.insertSecurityCheckManual(securityCheckManual);
        insertSecurityCheckManualMemberSubtable(securityCheckManual);
        return rows;
    }

    /**
     * 修改迎检报告信息主
     *
     * @param securityCheckManual 迎检报告信息主
     * @return 结果
     */
    @Transactional
    @Override
    public int updateSecurityCheckManual(SecurityCheckManual securityCheckManual)
    {
        Date now = DateUtils.getNowDate();
        securityCheckManual.setUpdateBy(SecurityUtils.getUserId()+"");
        securityCheckManual.setUpdateTime(now);

        securityCheckManualMapper.deleteSecurityCheckManualMemberSubtableByManualId(securityCheckManual.getId());
        securityCheckManualMapper.deleteSecurityCheckManualScheduleSubtableByManualId(securityCheckManual.getId());
        securityCheckManualMapper.deleteSecurityCheckManualPersonnelSubtableByManualId(securityCheckManual.getId());
        securityCheckManualMapper.deleteSecurityCheckManualDockingSubtableByManualId(securityCheckManual.getId());
        securityCheckManualMapper.deleteSecurityCheckManualCarSubtableByManualId(securityCheckManual.getId());
        insertSecurityCheckManualMemberSubtable(securityCheckManual);
        return securityCheckManualMapper.updateSecurityCheckManual(securityCheckManual);
    }

    /**
     * 批量删除迎检报告信息主
     *
     * @param ids 需要删除的迎检报告信息主主键
     * @return 结果
     */
    @Transactional
    @Override
    public int deleteSecurityCheckManualByIds(Long[] ids)
    {
        securityCheckManualMapper.deleteSecurityCheckManualMemberSubtableByManualIds(ids);
        securityCheckManualMapper.deleteSecurityCheckManualPersonnelSubtableByManualIds(ids);
        securityCheckManualMapper.deleteSecurityCheckManualScheduleSubtableByManualIds(ids);
        securityCheckManualMapper.deleteSecurityCheckManualDockingSubtableByManualIds(ids);
        securityCheckManualMapper.deleteSecurityCheckManualCarSubtableByManualIds(ids);
        return securityCheckManualMapper.deleteSecurityCheckManualByIds(ids);
    }

    /**
     * 删除迎检报告信息主信息
     *
     * @param id 迎检报告信息主主键
     * @return 结果
     */
    @Override
    public int deleteSecurityCheckManualById(Long id)
    {
        securityCheckManualMapper.deleteSecurityCheckManualMemberSubtableByManualId(id);
        securityCheckManualMapper.deleteSecurityCheckManualScheduleSubtableByManualId(id);
        securityCheckManualMapper.deleteSecurityCheckManualPersonnelSubtableByManualId(id);
        securityCheckManualMapper.deleteSecurityCheckManualDockingSubtableByManualId(id);
        securityCheckManualMapper.deleteSecurityCheckManualCarSubtableByManualId(id);
        return securityCheckManualMapper.deleteSecurityCheckManualById(id);
    }

    /**
     * 新增检查组成员信息
     *
     * @param securityCheckManual 迎检报告信息主对象
     */
    public void insertSecurityCheckManualMemberSubtable(SecurityCheckManual securityCheckManual)
    {
        List<SecurityCheckManualMemberSubtable> securityCheckManualMemberSubtableList = securityCheckManual.getSecurityCheckManualMemberSubtableList();
        List<SecurityCheckManualScheduleSubtable> securityCheckManualScheduleSubtableList = securityCheckManual.getSecurityCheckManualScheduleSubtableList();
        List<SecurityCheckManualPersonnelSubtable> securityCheckManualPersonnelSubtableList = securityCheckManual.getSecurityCheckManualPersonnelSubtableList();
        List<SecurityCheckManualDockingSubtable> securityCheckManualDockingSubtableList = securityCheckManual.getSecurityCheckManualDockingSubtableList();
        List<SecurityCheckManualCarSubtable> securityCheckManualCarSubtableList = securityCheckManual.getSecurityCheckManualCarSubtableList();

        Long id = securityCheckManual.getId();
        if (StringUtils.isNotNull(securityCheckManualMemberSubtableList))
        {
            List<SecurityCheckManualMemberSubtable> list = new ArrayList<SecurityCheckManualMemberSubtable>();
            for (SecurityCheckManualMemberSubtable securityCheckManualMemberSubtable : securityCheckManualMemberSubtableList)
            {
                securityCheckManualMemberSubtable.setManualId(id);
                list.add(securityCheckManualMemberSubtable);
            }
            if (list.size() > 0)
            {
                securityCheckManualMapper.batchSecurityCheckManualMemberSubtable(list);
            }
        }
        if (StringUtils.isNotNull(securityCheckManualScheduleSubtableList))
        {
            List<SecurityCheckManualScheduleSubtable> list = new ArrayList<SecurityCheckManualScheduleSubtable>();
            for (SecurityCheckManualScheduleSubtable securityCheckManualScheduleSubtable : securityCheckManualScheduleSubtableList)
            {
                securityCheckManualScheduleSubtable.setManualId(id);
                list.add(securityCheckManualScheduleSubtable);
            }
            if (list.size() > 0)
            {
                securityCheckManualMapper.batchSecurityCheckManualScheduleSubtable(list);
            }
        }
        if (StringUtils.isNotNull(securityCheckManualPersonnelSubtableList))
        {
            List<SecurityCheckManualPersonnelSubtable> list = new ArrayList<SecurityCheckManualPersonnelSubtable>();
            for (SecurityCheckManualPersonnelSubtable securityCheckManualPersonnelSubtable : securityCheckManualPersonnelSubtableList)
            {
                securityCheckManualPersonnelSubtable.setManualId(id);
                list.add(securityCheckManualPersonnelSubtable);
            }
            if (list.size() > 0)
            {
                securityCheckManualMapper.batchSecurityCheckManualPersonnelSubtable(list);
            }
        }
        if (StringUtils.isNotNull(securityCheckManualDockingSubtableList))
        {
            List<SecurityCheckManualDockingSubtable> list = new ArrayList<SecurityCheckManualDockingSubtable>();
            for (SecurityCheckManualDockingSubtable securityCheckManualDockingSubtable : securityCheckManualDockingSubtableList)
            {
                securityCheckManualDockingSubtable.setManualId(id);
                list.add(securityCheckManualDockingSubtable);
            }
            if (list.size() > 0)
            {
                securityCheckManualMapper.batchSecurityCheckManualDockingSubtable(list);
            }
        }
        if (StringUtils.isNotNull(securityCheckManualCarSubtableList))
        {
            List<SecurityCheckManualCarSubtable> list = new ArrayList<SecurityCheckManualCarSubtable>();
            for (SecurityCheckManualCarSubtable securityCheckManualCarSubtable : securityCheckManualCarSubtableList)
            {
                securityCheckManualCarSubtable.setManualId(id);
                list.add(securityCheckManualCarSubtable);
            }
            if (list.size() > 0)
            {
                securityCheckManualMapper.batchSecurityCheckManualCarSubtable(list);
            }
        }
    }

    @Override
    public List<WeatherReport> get7DayWeatherReport()
    {
        String url = "https://m.weathercn.com/daily-weather-forecast.do?partner=1000001071_hfaw&id=1849236&p_source=&p_type=jump&day=";
        LocalDate localDate = LocalDate.now();
        String regex = "\\d+";
        Pattern pattern = Pattern.compile(regex);
        List<WeatherReport> weatherReports = new ArrayList<>();
        try
        {
            for (int i = 1; i <= 8; i++)
            {
                Document doc = Jsoup.connect(url + i).timeout(5000).userAgent("PostmanRuntime/7.28.1").get();

                String maxWind = doc.select(".details-light > .days-details-right > p.js-wind").text();
                String minWind = doc.select(".details-night > .days-details-right > p.js-wind").text();
                Matcher matcher = pattern.matcher(maxWind);
                if (matcher.find())
                {
                    maxWind = matcher.group();
                }
                String wind = minWind.replace("级", "-" + maxWind + "级");
                if (minWind.equals(maxWind))
                {
                    wind = minWind;
                }
                String maxTemp = doc.select(".details-light > .days-details-left > p").text();
                String minTemp = doc.select(".details-night > .days-details-left > p").text();
                String temp = minTemp.replace("℃", "/" + maxTemp);
                if (minTemp.equals(maxTemp))
                {
                    temp = minTemp;
                }
                String weatherDesc = doc.select(".details-light > .days-details-left > .left-icon > div > .js-weather-text").text();
                String pic = doc.select(".details-light > .days-details-left > .left-icon > div > img").attr("src");
                String dayName = localDate.plusDays(i - 1).format(DateTimeFormatter.ofPattern("MM-dd"));
                if (i == 1) {
                    dayName = "今天(" + dayName + ")";
                }
                else if (i == 2) {
                    dayName = "明天(" + dayName + ")";
                }
                else {
                    dayName = localDate.plusDays(i - 1).getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.CHINA) + "(" + dayName + ")";
                }
//                String pre = doc.select(".rain-light > .days-rain-charts  .js-light-rain-mm").text();
                WeatherReport weatherReport = new WeatherReport();
                weatherReport.setWeatherDesc(weatherDesc);
                weatherReport.setDayName(dayName);
                weatherReport.setWeatherPic("http:" + pic);
                weatherReport.setWind(wind);
                weatherReport.setTemperature(temp);
                weatherReports.add(weatherReport);
            }
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        return weatherReports;
    }

    @Override
    public void downloadReport(Long id, HttpServletResponse response)
    {
        SecurityCheckManual securityCheckManual = selectSecurityCheckManualById(id);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日");
        InputStream templateFile = null;
        try
        {
            URL uri = new URL(templateConfig.getTemplate());
            templateFile = uri.openStream();
        }
        catch (IOException e)
        {
            e.printStackTrace();
            return;
        }
        System.out.println(templateConfig.getTemplate());
        Map<String, Object> texts = new HashMap<>();
        String title = securityCheckManual.getTitle();
        texts.put("title", title);
        Date editDate = securityCheckManual.getManualDate();
        texts.put("editDate", editDate == null ? LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy年MM月dd日")) : simpleDateFormat.format(editDate) );
        String xietiao = securityCheckManual.getWorkCoordinator();
        String jiesong = securityCheckManual.getTransferPersonnel();
        String yingji = securityCheckManual.getAntiepidemicPersonnel();
        texts.put("xietiao", jsonToStandStr(xietiao));
        texts.put("jiesong", jsonToStandStr(jiesong));
        texts.put("yingji", jsonToStandStr(yingji));
        texts.put("weather", get7DayWeatherReport());
        List<SecurityCheckManualMemberSubtable> chceckers = securityCheckManual.getSecurityCheckManualMemberSubtableList();
        for (int i = 0; i < chceckers.size(); i++)
        {
            SecurityCheckManualMemberSubtable checker = chceckers.get(i);
            checker.setId(Long.valueOf(i + 1));
        }
        texts.put("chceckers", chceckers);
        List<SecurityCheckManualPersonnelSubtable> persons = securityCheckManual.getSecurityCheckManualPersonnelSubtableList();
        for (int i = 0; i < persons.size(); i++)
        {
            SecurityCheckManualPersonnelSubtable person = persons.get(i);
            person.setId(Long.valueOf(i +1));
        }
        texts.put("persons", persons);
        List<SecurityCheckManualScheduleSubtable> schedules = securityCheckManual.getSecurityCheckManualScheduleSubtableList();
        List<SecurityCheckManualScheduleSubtable> schedulesOrdered = schedules.stream()
                .sorted(Comparator.comparing(SecurityCheckManualScheduleSubtable::getScheduleDate, Comparator.reverseOrder())
                        .thenComparing(SecurityCheckManualScheduleSubtable::getScheduleTime, Comparator.reverseOrder())).collect(Collectors.toList());
        List<RowRenderData> rows = new ArrayList<>();
        for (int i = 0; i < schedulesOrdered.size(); i++)
        {
            SecurityCheckManualScheduleSubtable sc = schedules.get(i);
            RowRenderData rowRenderData = Rows.of(sc.getScheduleDate(), sc.getScheduleTime(), sc.getSchedule(), sc.getPlace(), sc.getRemarks()).center().create();
            rows.add(rowRenderData);
        }
        texts.put("schedule", rows); //ll
        List<SecurityCheckManualDockingSubtable> docking = securityCheckManual.getSecurityCheckManualDockingSubtableList();
        for (int i = 0; i < docking.size(); i++)
        {
            SecurityCheckManualDockingSubtable docker = docking.get(i);
            docker.setId(Long.valueOf(i +1));
        }
        texts.put("docking", docking);
        List<SecurityCheckManualCarSubtable> cars = securityCheckManual.getSecurityCheckManualCarSubtableList();
        for (int i = 0; i < cars.size(); i++)
        {
            SecurityCheckManualCarSubtable car = cars.get(i);
            car.setId(Long.valueOf(i + 1));
        }
        texts.put("car", cars);
        LoopRowTableRenderPolicy policy = new LoopRowTableRenderPolicy();
        SchedulePolicy schedulePolicy = new SchedulePolicy();
        Configure config = Configure.builder()
                .bind("chceckers", policy)
                .bind("persons", policy)
                .bind("schedule", schedulePolicy)
                .bind("weather", new LoopColumnTableRenderPolicy())
                .bind("car", policy)
                .bind("chechers", policy)
                .bind("docking", policy)
                .build();
        XWPFTemplate template = XWPFTemplate.compile(templateFile, config);
        response.setCharacterEncoding("utf-8");
        response.setContentType("application/force-download");// 设置强制下载不打开
//                response.addHeader("Content-Disposition", "attachment;fileName=" + new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1));
        title += ".docx";
        response.setHeader("Content-Disposition", "attach;filename=" + new String(title.getBytes(StandardCharsets.UTF_8) , StandardCharsets.ISO_8859_1));
        try
        {
            OutputStream outputStream = response.getOutputStream();
            template.render(texts);
            template.writeAndClose(outputStream);
        }
        catch (IOException e)
        {
            logger.error("download check report fail: " + e.getMessage());
        }
    }

    private String jsonToStandStr(String src)
    {
        JSONArray xieArr = JSONArray.parseArray(src);
        List<String> xietiao4doc = new ArrayList<>();
        for (int i = 0; i < xieArr.size(); i++)
        {
            JSONObject person = xieArr.getJSONObject(i);
            xietiao4doc.add(person.getString("name") + "  " + person.getString("phone"));
        }
        return StringUtils.join(xietiao4doc, " \n\t\t\t\t  ");
    }
}
